<?php

declare(strict_types=1);

namespace app\service\user;

use app\service\dto\TokenPair;
use Firebase\JWT\JWT;
use Firebase\JWT\Key;
use app\service\sys\ConfigService;

class PartialTokenService
{
    private $key = '';
    private $expire = 3 * 24 * 3600; //3天

    public function __construct(ConfigService $configService)
    {
        $config = $configService->get('jwt');
        $this->key = $config['key'] ?? 'bearing_shop_default_key';
    }

    /**
     * 生成部分令牌数据
     * @param array $payload 令牌载荷
     * @return string 生成的部分令牌数据
     */
    public function generatePartialTokenData($payload): TokenPair
    {
        $currentTime = time();
        // 创建部分 JWT 令牌
        $payload = array_merge($payload, [
            'partial' => true,
            'exp' => $currentTime + $this->expire,
            'iat' => $currentTime,
            'type' => 'partial'
        ]);
        return new TokenPair(
            JWT::encode($payload, $this->key, 'HS256'),
            '',
            date('Y-m-d H:i:s', $currentTime + $this->expire),
        );
    }

    /**
     * 验证部分令牌
     * @param string $token JWT令牌
     * @return array 解码后的载荷
     * @throws \Exception
     */
    public function validatePartialToken($token)
    {
        try {
            $decoded = JWT::decode($token, new Key($this->key, 'HS256'));

            // 检查令牌类型
            if ($decoded->type !== 'partial') {
                throw new \Exception('令牌类型不匹配', 402);
            }

            // 检查是否过期
            if ($decoded->exp < time()) {
                throw new \Exception('令牌已过期', 401);
            }

            // 检查是否为部分令牌
            if (!isset($decoded->partial) || !$decoded->partial) {
                throw new \Exception('不是部分令牌', 402);
            }

            return (array) $decoded;
        } catch (\Exception $e) {
            throw new \Exception($e->getMessage(), $e->getCode() ?: 401);
        }
    }
}
